package com.atguigu.gmall.activity.service.impl;

import com.atguigu.gmall.activity.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.activity.service.SeckillGoodsService;
import com.atguigu.gmall.activity.util.CacheHelper;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.result.ResultCodeEnum;
import com.atguigu.gmall.common.util.MD5;
import com.atguigu.gmall.model.activity.OrderRecode;
import com.atguigu.gmall.model.activity.SeckillGoods;
import jodd.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author ：Shine
 * @description：
 * @date ：2021/3/10 23:38
 */
@Service
public class SeckillGoodsServiceImpl implements SeckillGoodsService {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    @Override
    public List<SeckillGoods> findAll() {
        List<SeckillGoods> seckillGoodsList = redisTemplate.boundHashOps(RedisConst.SECKILL_GOODS).values();
        return seckillGoodsList;
    }

    @Override
    public SeckillGoods getSeckillGoodsById(Long skuId) {
        SeckillGoods skuInfo = (SeckillGoods) redisTemplate.boundHashOps(RedisConst.SECKILL_GOODS).get(skuId.toString());
        return skuInfo;
    }

    @Override
    public void seckillOrder(String userId, Long skuId) {
        String status = (String) CacheHelper.get(skuId.toString());
        if ("0".equals(status) || StringUtil.isEmpty(status)) {
            return;
        }

        //    判断用户是否已经下过订单，使用Redis中的setnx（key，value）,字符串那类型的才有这个命令
        String userRecodeKey = RedisConst.SECKILL_USER + userId;
        Boolean flag = redisTemplate.opsForValue().setIfAbsent(userRecodeKey, skuId, RedisConst.SKUKEY_TIMEOUT, TimeUnit.SECONDS);
        if (!flag) {
            //      表示当前用户不是第一次下单
            return;
        }

        //    库存数量减一
        String secKillListKey = RedisConst.SECKILL_STOCK_PREFIX + skuId.toString();
        String redisSkuId = (String) redisTemplate.boundListOps(secKillListKey).rightPop();
        if (StringUtil.isEmpty(redisSkuId)) {
            //    该商品已经售完，通知其他节点
            redisTemplate.convertAndSend("seckillpush", skuId.toString() + ":0");
            return;
        }

        //    上述都没问题的话将用户下单记录保存到缓存中
        OrderRecode orderRecode = new OrderRecode();
        orderRecode.setNum(1);
        orderRecode.setOrderStr(MD5.encrypt(userId + skuId));
        orderRecode.setSeckillGoods(this.getSeckillGoodsById(skuId));
        orderRecode.setUserId(userId);
        redisTemplate.boundHashOps(RedisConst.SECKILL_ORDERS).put(userId, orderRecode);

        //    更新数据库
        this.updateStock(skuId);
    }

    @Override
    public Result checkOrder(Long skuId, String userId) {
        String userRecodeKey = RedisConst.SECKILL_USER + userId;
        Boolean flag = redisTemplate.hasKey(userRecodeKey);
        if (flag) {
            //判断用户是否有预下单记录
            Boolean result = redisTemplate.boundHashOps(RedisConst.SECKILL_ORDERS).hasKey(userId);
            if (result) {
                //用户抢单成功
                OrderRecode orderRecode = (OrderRecode) redisTemplate.boundHashOps(RedisConst.SECKILL_ORDERS).get(userId);
                return Result.build(orderRecode, ResultCodeEnum.SECKILL_SUCCESS);
            }
        }

        //判断用户是否真下过订单
        String orderKey = RedisConst.SECKILL_ORDERS_USERS;
        Boolean orderFlag = redisTemplate.boundHashOps(orderKey).hasKey(userId);
        if (orderFlag) {
            //        用户已经秒杀成功且已经下过单
            String orderId = (String) redisTemplate.boundHashOps(orderKey).get(userId);
            return Result.build(orderId, ResultCodeEnum.SECKILL_ORDER_SUCCESS);
        }

        //判断状态位
        String status = (String) CacheHelper.get(skuId.toString());
        if (StringUtil.isEmpty(status) || "0".equals(status)) {
            return Result.build(null, ResultCodeEnum.FAIL);
        }

        //给一个默认值
        return Result.build(null, ResultCodeEnum.SECKILL_RUN);
    }

    private void updateStock(Long skuId) {
        String secKillListKey = RedisConst.SECKILL_STOCK_PREFIX + skuId.toString();
        Long count = redisTemplate.boundListOps(secKillListKey).size();
        //    更新缓存和数据库
        if (count % 2 == 0) {
            SeckillGoods seckillGoods = this.getSeckillGoodsById(skuId);
            seckillGoods.setStockCount(count.intValue());
            seckillGoodsMapper.updateById(seckillGoods);
            redisTemplate.boundHashOps(RedisConst.SECKILL_GOODS).put(skuId.toString(), seckillGoods);

        }
    }
}
